import { relations, sql } from 'drizzle-orm';
import {
  bigserial,
  doublePrecision,
  jsonb,
  numeric,
  pgEnum,
  pgTable,
  text,
  time,
  timestamp,
  varchar,
} from 'drizzle-orm/pg-core';
import { user } from './auth';
import { orderStatusValues, shopStatusValues } from './enum';

export const shopStatus = pgEnum('shop_status', shopStatusValues);

export const shop = pgTable('shop', {
  id: bigserial('id', { mode: 'number' }).primaryKey(),
  userId: text('user_id')
    .references(() => user.id)
    .notNull(),
  name: varchar('name', { length: 100 }).notNull(),
  description: text('description'),
  address: text('address').notNull(),
  longitude: doublePrecision('longitude').notNull(),
  latitude: doublePrecision('latitude').notNull(),
  contactPhone: varchar('contact_phone', { length: 15 }).notNull(),
  imageKeys: jsonb('image_keys').$type<string[]>().notNull().default([]),
  status: shopStatus().notNull().default('unreviewed'),
  licenseKey: varchar('license_key', { length: 255 }),
  hygieneCertKey: varchar('hygiene_cert_key', { length: 255 }),
  rejectReason: text('reject_reason').default(''),
  warningReason: text('warning_reason').default(''),
  createdAt: timestamp('created_at').notNull().defaultNow(),
  updatedAt: timestamp('updated_at')
    .notNull()
    .defaultNow()
    .$onUpdateFn(() => new Date()),
  startTime: time('start_time', { precision: 0 }).notNull().defaultNow(),
  endTime: time('end_time', { precision: 0 }).notNull().defaultNow(),
  deliveryMinPrice: numeric('delivery_min_price', {
    precision: 10,
    scale: 2,
  })
    .notNull()
    .default(sql`0.00`),
  rating: numeric('rating', { precision: 3, scale: 2 })
    .notNull()
    .default(sql`5.00`),
});

export const shopRelations = relations(shop, ({ one, many }) => ({
  user: one(user, {
    fields: [shop.userId],
    references: [user.id],
  }),
  products: many(product),
}));

export const orderStatus = pgEnum('order_status', orderStatusValues);

export const order = pgTable('order', {
  id: bigserial('id', { mode: 'number' }).primaryKey(),
  userId: text('user_id')
    .references(() => user.id)
    .notNull(),
  shopId: bigserial('shop_id', { mode: 'number' })
    .references(() => shop.id)
    .notNull(),
  address: varchar('address', { length: 100 }).notNull(),
  userPhone: varchar('user_phone', { length: 15 }).notNull(),
  userName: varchar('user_name', { length: 15 }).notNull(),
  remark: text('remark'),
  status: orderStatus().notNull().default('unpaid'),
  products: jsonb('products')
    .$type<{ id: number; count: number }[]>()
    .notNull()
    .default([]),
  evaluation: jsonb('evaluation')
    .$type<{ product: number; deliver: number }>()
    .notNull()
    .default({
      product: 5,
      deliver: 5,
    }),
  createdAt: timestamp('created_at').notNull().defaultNow(),
});

export const orderRelations = relations(order, ({ one }) => ({
  user: one(user, {
    fields: [order.userId],
    references: [user.id],
  }),
  shop: one(shop, {
    fields: [order.shopId],
    references: [shop.id],
  }),
}));

export const product = pgTable('product', {
  id: bigserial('id', { mode: 'number' }).primaryKey(),
  shopId: bigserial('shop_id', { mode: 'number' })
    .references(() => shop.id)
    .notNull(),
  name: varchar('name', { length: 100 }).notNull(),
  price: numeric('price', { precision: 10, scale: 2 }).notNull(),
  imageKeys: jsonb('image_keys').$type<string[]>().notNull().default([]),
  description: text('description'),
  createdAt: timestamp('created_at').notNull().defaultNow(),
  updatedAt: timestamp('updated_at')
    .notNull()
    .defaultNow()
    .$onUpdateFn(() => new Date()),
});

export const productRelations = relations(product, ({ one }) => ({
  shop: one(shop, {
    fields: [product.shopId],
    references: [shop.id],
  }),
}));

export const address = pgTable('address', {
  id: bigserial('id', { mode: 'number' }).primaryKey(),
  poiId: text('poi_id').notNull(),
  userId: text('user_id')
    .references(() => user.id)
    .notNull(),
  name: text('name').notNull(),
  phone: text('phone').notNull(),
  address: text('address').notNull(),
  longitude: doublePrecision('longitude').notNull().default(0),
  latitude: doublePrecision('latitude').notNull().default(0),
  createdAt: timestamp('created_at').notNull().defaultNow(),
  updatedAt: timestamp('updated_at')
    .notNull()
    .defaultNow()
    .$onUpdateFn(() => new Date()),
});

export const addressRelations = relations(address, ({ one }) => ({
  user: one(user, {
    fields: [address.userId],
    references: [user.id],
  }),
}));

export const userRelations = relations(user, ({ many, one }) => ({
  addresses: many(address),
  shop: one(shop, {
    fields: [user.id],
    references: [shop.userId],
  }),
}));
